#pragma once
// 实现语音识别子服务
#include <brpc/server.h>
#include <butil/logging.h>

#include "asr.h"       // 语音识别模块封装
#include "etcd.h"      // 服务注册模块封装
#include "logger.h"    // 日志模块封装
#include "speech.pb.h" // protobuf框架代码

// 定义语言识别服务业务类
class SpeechServiceImpl : public ljm::SpeechService
{
public:
    SpeechServiceImpl(const ASRClient::ptr &asr_cli) : _asr_cli(asr_cli)
    {
    }

    // 重写服务函数
    void SpeechRecognition(google::protobuf::RpcController *controller,
                           const ::ljm::SpeechRecognitionReq *request,
                           ::ljm::SpeechRecognitionRsp *response,
                           ::google::protobuf::Closure *done)
    {
        LOG_DEBUG("收到语音转文字请求！");
        brpc::ClosureGuard rpc_guard(done); // 将done交给guard进行管理, 析构时自动调用run函数
        // 获取请求数据并进行业务处理
        std::string err;
        std::string res = _asr_cli->recognize(request->speech_content(), err);
        if (res.empty())
        {
            LOG_ERROR("{} 语音识别失败！", request->request_id());
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg("语音识别失败:" + err);
            return;
        }
        // 组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_recognition_result(res);
    }

    ~SpeechServiceImpl()
    {
    }

private:
    ASRClient::ptr _asr_cli; // 语言识别客户端对象
};

// 语言识别服务端类
class SpeechServer
{
public:
    using ptr = std::shared_ptr<SpeechServer>;

    SpeechServer(const ASRClient::ptr &asr_cli, const Register::ptr &reg, const std::shared_ptr<brpc::Server> &brpc_server)
        : _asr_cli(asr_cli), _reg(reg), _brpc_server(brpc_server)
    {
    }

    void start()
    {
        _brpc_server->RunUntilAskedToQuit();
    }

    ~SpeechServer()
    {
    }

private:
    ASRClient::ptr _asr_cli;                    // 语言识别客户端对象
    Register::ptr _reg;                         // 注册服务对象
    std::shared_ptr<brpc::Server> _brpc_server; // brpc服务端对象
};

// 语言识别服务端建造类
class SpeechServerBuilder
{
public:
    SpeechServerBuilder() {}

    // 构造语音识别客户端对象
    void make_asr_object(const std::string &app_id,
                         const std::string &api_key,
                         const std::string &secret_key)
    {
        _asr_cli = std::make_shared<ASRClient>(app_id, api_key, secret_key);
    }

    // 用于构造服务注册客户端对象
    void make_reg_object(const std::string &reg_host,
                         const std::string &service_name,
                         const std::string &access_addr)
    {
        _reg = std::make_shared<Register>(reg_host);
        _reg->registry(service_name, access_addr);
    }

    // 构造RPC服务器对象
    void make_brpc_server(uint16_t port, int32_t timeout, uint8_t num_threads)
    {
        if (!_asr_cli)
        {
            LOG_ERROR("还未初始化语音识别模块");
            abort();
        }

        _brpc_server = std::make_shared<brpc::Server>();
        SpeechServiceImpl *ssi = new SpeechServiceImpl(_asr_cli);
        int res = _brpc_server->AddService(ssi, brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
        if (res == -1)
        {
            LOG_ERROR("添加Rpc服务失败");
            abort();
        }

        brpc::ServerOptions options;
        options.idle_timeout_sec = timeout;
        options.num_threads = num_threads;

        // 启动brpc服务
        res = _brpc_server->Start(port, &options);
        if (res == -1)
        {
            LOG_ERROR("启动Rpc服务失败");
            abort();
        }
    }

    SpeechServer::ptr build()
    {
        if (!_asr_cli)
        {
            LOG_ERROR("还未初始化语音识别模块");
            abort();
        }
        if (!_reg)
        {
            LOG_ERROR("还未初始化服务注册模块");
            abort();
        }
        if (!_brpc_server)
        {
            LOG_ERROR("还未初始化RPC服务器模块");
            abort();
        }
        SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_cli, _reg, _brpc_server);
        return server;
    }

    ~SpeechServerBuilder()
    {
    }

private:
    ASRClient::ptr _asr_cli;                    // 语言识别客户端对象
    Register::ptr _reg;                         // 注册服务对象
    std::shared_ptr<brpc::Server> _brpc_server; // brpc服务端对象
};